"""
Seaborn 颜色和样式定制示例

知识点：
1. 使用内置调色板（palette）
2. 自定义颜色映射
3. 设置主题样式（theme 和 style）
4. 使用 context 调整图表元素大小
5. 自定义颜色渐变
6. 色盲友好的配色方案
"""

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 设置中文字体（在使用 sns.set_theme 之前先配置）
plt.rcParams['font.sans-serif'] = ['PingFang HK', 'Hiragino Sans GB', 'STHeiti', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'

# 创建示例数据
np.random.seed(42)
n = 100
categories = ['类别A', '类别B', '类别C', '类别D']

data = pd.DataFrame({
    'X值': np.random.randn(n) * 10 + 50,
    'Y值': np.random.randn(n) * 15 + 60,
    '类别': np.random.choice(categories, n),
    '数值': np.random.uniform(10, 100, n),
    '分组': np.random.choice(['组1', '组2'], n)
})

# 示例1: 内置调色板对比
print("=" * 60)
print("示例1: Seaborn 内置调色板")
print("=" * 60)

palettes = ['deep', 'muted', 'pastel', 'bright', 'dark', 'colorblind']
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
fig.suptitle('Seaborn 内置调色板对比', fontsize=16, fontweight='bold')

for idx, palette in enumerate(palettes):
    ax = axes[idx // 3, idx % 3]
    sns.scatterplot(
        data=data,
        x='X值',
        y='Y值',
        hue='类别',
        palette=palette,
        s=100,
        alpha=0.7,
        ax=ax
    )
    ax.set_title(f'palette="{palette}"', fontweight='bold', fontsize=12)
    ax.legend(title='类别', fontsize=8)

plt.tight_layout()
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/5-1-内置调色板.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 示例2: 自定义颜色映射
print("\n" + "=" * 60)
print("示例2: 自定义颜色映射")
print("=" * 60)

fig, axes = plt.subplots(1, 3, figsize=(18, 5))
fig.suptitle('自定义颜色映射方法', fontsize=16, fontweight='bold')

# 方法1: 使用颜色列表
custom_colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A']
sns.scatterplot(
    data=data,
    x='X值',
    y='Y值',
    hue='类别',
    palette=custom_colors,
    s=120,
    alpha=0.7,
    ax=axes[0]
)
axes[0].set_title('方法1: 使用颜色列表', fontweight='bold')

# 方法2: 使用字典映射
color_dict = {
    '类别A': '#E74C3C',
    '类别B': '#3498DB',
    '类别C': '#2ECC71',
    '类别D': '#F39C12'
}
sns.scatterplot(
    data=data,
    x='X值',
    y='Y值',
    hue='类别',
    palette=color_dict,
    s=120,
    alpha=0.7,
    ax=axes[1]
)
axes[1].set_title('方法2: 使用字典映射', fontweight='bold')

# 方法3: 使用 matplotlib 颜色映射
sns.scatterplot(
    data=data,
    x='X值',
    y='Y值',
    hue='数值',  # 连续变量
    palette='coolwarm',  # matplotlib colormap
    size='数值',
    sizes=(50, 300),
    alpha=0.7,
    ax=axes[2]
)
axes[2].set_title('方法3: 连续变量用渐变色', fontweight='bold')

plt.tight_layout()
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/5-2-自定义颜色.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 示例3: 主题样式对比
print("\n" + "=" * 60)
print("示例3: Seaborn 主题样式")
print("=" * 60)

styles = ['darkgrid', 'whitegrid', 'dark', 'white', 'ticks']
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
fig.suptitle('Seaborn 主题样式对比', fontsize=16, fontweight='bold')

for idx, style in enumerate(styles):
    if idx < len(axes.flat):
        ax = axes.flat[idx]
        sns.set_style(style)
        sns.scatterplot(
            data=data,
            x='X值',
            y='Y值',
            hue='类别',
            palette='Set2',
            s=100,
            alpha=0.7,
            ax=ax
        )
        ax.set_title(f'style="{style}"', fontweight='bold', fontsize=12)

# 隐藏最后一个空白子图
axes.flat[-1].axis('off')

plt.tight_layout()
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/5-3-主题样式.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 恢复默认样式
sns.set_style('whitegrid')

# 示例4: Context 上下文设置（调整元素大小）
print("\n" + "=" * 60)
print("示例4: Context 上下文设置")
print("=" * 60)

contexts = ['paper', 'notebook', 'talk', 'poster']
fig, axes = plt.subplots(2, 2, figsize=(16, 12))
fig.suptitle('Context 上下文设置对比（调整元素大小）', fontsize=16, fontweight='bold')

for idx, context in enumerate(contexts):
    ax = axes[idx // 2, idx % 2]
    sns.set_context(context)
    sns.scatterplot(
        data=data,
        x='X值',
        y='Y值',
        hue='类别',
        palette='husl',
        s=100,
        alpha=0.7,
        ax=ax
    )
    ax.set_title(f'context="{context}"', fontweight='bold')

plt.tight_layout()
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/5-4-context设置.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 恢复默认context
sns.set_context('notebook')

# 示例5: 渐变色调色板（用于连续变量）
print("\n" + "=" * 60)
print("示例5: 渐变色调色板")
print("=" * 60)

gradient_palettes = ['viridis', 'plasma', 'inferno', 'magma', 'cividis', 'coolwarm']
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
fig.suptitle('渐变色调色板对比（适用于连续变量）', fontsize=16, fontweight='bold')

for idx, palette in enumerate(gradient_palettes):
    ax = axes[idx // 3, idx % 3]
    scatter = sns.scatterplot(
        data=data,
        x='X值',
        y='Y值',
        hue='数值',  # 连续变量
        palette=palette,
        s=120,
        alpha=0.8,
        ax=ax
    )
    ax.set_title(f'palette="{palette}"', fontweight='bold', fontsize=12)
    # 调整colorbar
    norm = plt.Normalize(vmin=data['数值'].min(), vmax=data['数值'].max())
    sm = plt.cm.ScalarMappable(cmap=palette, norm=norm)
    sm.set_array([])

plt.tight_layout()
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/5-5-渐变色.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 示例6: 综合应用 - 创建专业的可视化
print("\n" + "=" * 60)
print("示例6: 综合应用 - 专业可视化")
print("=" * 60)

# 设置专业主题
sns.set_theme(style='ticks', context='talk')

fig, ax = plt.subplots(figsize=(12, 8))

# 使用自定义配色和样式
custom_palette = {
    '类别A': '#E63946',
    '类别B': '#457B9D',
    '类别C': '#2A9D8F',
    '类别D': '#E9C46A'
}

scatter = sns.scatterplot(
    data=data,
    x='X值',
    y='Y值',
    hue='类别',
    size='数值',
    style='分组',
    palette=custom_palette,
    sizes=(100, 500),
    alpha=0.7,
    edgecolor='white',
    linewidth=1.5,
    ax=ax
)

# 美化图表
ax.set_title('专业数据可视化示例\n多维度综合展示', 
             fontsize=16, fontweight='bold', pad=20)
ax.set_xlabel('X 轴数值', fontsize=14, fontweight='bold')
ax.set_ylabel('Y 轴数值', fontsize=14, fontweight='bold')
ax.grid(True, alpha=0.3, linestyle='--')

# 优化图例
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels, 
          title='图例', 
          title_fontsize=12,
          fontsize=10,
          loc='upper left',
          frameon=True,
          fancybox=True,
          shadow=True)

# 移除上方和右侧的边框
sns.despine()

plt.tight_layout()
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/5-6-综合应用.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 恢复默认设置
sns.set_theme()

print("\n" + "=" * 60)
print("颜色和样式定制总结")
print("=" * 60)
print("\n1. 内置调色板：")
print("   - deep, muted, pastel, bright, dark, colorblind")
print("   - Set1, Set2, Set3, Paired, tab10")

print("\n2. 渐变色（连续变量）：")
print("   - viridis, plasma, inferno, magma (感知均匀)")
print("   - coolwarm, RdYlBu (发散型)")
print("   - Blues, Greens, Reds (单色渐变)")

print("\n3. 主题样式：")
print("   - darkgrid: 深色网格（默认）")
print("   - whitegrid: 白色背景 + 网格")
print("   - dark: 深色背景无网格")
print("   - white: 白色背景无网格")
print("   - ticks: 白色背景 + 刻度线")

print("\n4. Context 上下文：")
print("   - paper: 适合论文（最小）")
print("   - notebook: 适合笔记本（默认）")
print("   - talk: 适合演讲")
print("   - poster: 适合海报（最大）")

print("\n5. 自定义颜色方法：")
print("   - 列表: ['#FF0000', '#00FF00', '#0000FF']")
print("   - 字典: {'A': '#FF0000', 'B': '#00FF00'}")
print("   - matplotlib colormap: 'viridis', 'coolwarm' 等")

print("\n6. 最佳实践：")
print("   - 分类数据用离散调色板")
print("   - 连续数据用渐变调色板")
print("   - 考虑色盲友好配色")
print("   - 添加边框和透明度增强可读性")
print("=" * 60)
